package com.cm.projectx.job.service.impl;

import com.cm.projectx.common.entity.UserContext;
import com.cm.projectx.job.service.ScheduleService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

@Service
public class ScheduleServiceImpl implements ScheduleService {

    private static Logger logger = LoggerFactory.getLogger(ScheduleServiceImpl.class);


    @Autowired
    private Scheduler scheduler;

    @Override
    public void addSchedule(int taskId, String jobName, String jobGroup, String jobClassName, String triggerName, String triggerGroup, String cronExpression, Date startTime, Date endTime) {
        try {
            String userId = UserContext.getCurrentUser().getUserId();
            String idCardName = UserContext.getCurrentUser().getIdCardName();
            String token = UserContext.getCurrentUser().getToken();
            // 1. 首先验证触发时间是否有效
            CronExpression cronExpr = new CronExpression(cronExpression);
            cronExpr.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置时区
            // 计算第一个在开始时间之后的触发点
            Date nextFireTime = cronExpr.getNextValidTimeAfter(startTime);
            // 格式化并记录日志
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (nextFireTime != null) {
                logger.info("cron为：{}计算第一个在开始时间之后的触发点，任务将在以下时间执行: {}",cronExpression, sdf.format(nextFireTime));
            } else {
                logger.info("任务没有找到下一次执行时间");
            }

            if (nextFireTime == null) {
                // Cron表达式在开始时间后没有任何触发点（例如：设置了一个永远不可能出现的日期）
                throw new IllegalArgumentException("错误：Cron表达式 '" + cronExpression + "' 在开始时间 " + startTime + " 之后永远不会触发。");
            }
            if (endTime != null && nextFireTime.after(endTime)) {
                // 第一个触发点就在结束时间之后，说明在整个时间窗口内都没有触发点
                throw new IllegalArgumentException("错误：在开始时间 " + startTime + " 和结束时间 " + endTime + " 之间，Cron表达式 '" + cronExpression + "' 没有任何触发点。");
            }
            Class<?> className = Class.forName(jobClassName);
            QuartzJobBean jobBean = (QuartzJobBean) className.newInstance();
            JobDataMap newJobDataMap = new JobDataMap();
            newJobDataMap.putAsString("taskId", taskId);
            newJobDataMap.put("userId", userId);
            newJobDataMap.put("idCardName", idCardName);
            newJobDataMap.put("token",token);
            JobDetail jobDetail = JobBuilder.newJob(jobBean.getClass())
                    .setJobData(newJobDataMap)
                    .withIdentity(jobName, jobGroup)
                    .storeDurably()
                    .build();

//            Trigger immediateTrigger = TriggerBuilder.newTrigger()
//                    .withIdentity(triggerName + "_IMMEDIATE", triggerGroup + "_IMMEDIATE")
//                    .startNow() // 立即执行
//                    .forJob(jobDetail)
//                    .build();
//            scheduler.scheduleJob(jobDetail, immediateTrigger);
            CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerName, triggerGroup)
                    .withSchedule(
                            CronScheduleBuilder.cronSchedule(cronExpression)
                            .inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))// 明确设置时区
                            //明确设置 misfire 策略
                            // 选项1：忽略所有错过的执行
                           // .withMisfireHandlingInstructionDoNothing()
                            // 选项2：立即执行所有错过的执行
                            .withMisfireHandlingInstructionIgnoreMisfires()
                            // 选项3：立即执行一次，然后按计划继续（默认行为）
                            //.withMisfireHandlingInstructionFireAndProceed()
                    )
                    .startAt(startTime)
                    .endAt(endTime)
                    .build();
            scheduler.scheduleJob(jobDetail, cronTrigger);
        } catch (Exception e) {
            logger.error("添加任务异常", e);
            throw new RuntimeException("添加定时任务失败", e);
        }
    }

    @Override
    public void pauseSchedule(String jobName, String jobGroup) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
        } catch (Exception e) {
            logger.error("暂停任务异常", e);
        }
    }

    @Override
    public void resumeSchedule(String jobName, String jobGroup) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
        } catch (Exception e) {
            logger.error("调起任务异常", e);
        }
    }

    @Override
    public void deleteSchedule(String jobName, String jobGroup) {
        try {
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            logger.error("删除任务异常", e);
        }
    }
}
